
module image_switches(
input clk_out,
input rst_p,
input wr_clk1,
input [15:0]data1,
input data_valid1,
input [15:0]data2,
input data_valid2,
input wr_clk2,
output reg[15:0]image_data,
output image_valid
    );
 parameter image_cnt1 = 16'd400;
 parameter image_cnt2 = 16'd400;
wire rst_busy_o;
wire wr_rst_busy1;
wire rd_rst_busy1;
wire wr_rst_busy2;
wire rd_rst_busy2;
wire full1;       
wire almost_full1;
wire empty1;
wire full2;       
wire almost_full2;
wire empty2;      
reg[3:0]cur_state;
reg[3:0]next_state;
reg image_choose;
reg[11:0]RD_cnt;
wire rd_en1;
wire rd_en2;
parameter IDEL = 4'b0001;
parameter ARB = 4'b0010;
parameter RD_IMG1 = 4'b0100;
parameter RD_IMG2 = 4'b1000;
wire[15:0]dout1;
wire[15:0]dout2;
assign rst_busy_o = wr_rst_busy1||rd_rst_busy1||wr_rst_busy2||rd_rst_busy2;
assign rd_en1 = (next_state == RD_IMG1)&&(~empty1)&&(RD_cnt<image_cnt1);
assign rd_en2 = (next_state == RD_IMG2)&&(~empty2)&&(RD_cnt<image_cnt2);

image_buffer image_buffer1 (
  .rst(rst_p),                      // input wire rst
  .wr_clk(wr_clk1),                // input wire wr_clk
  .rd_clk(clk_out),                // input wire rd_clk
  .din(data1),                      // input wire [15 : 0] din
  .wr_en(data_valid1),                  // input wire wr_en
  .rd_en(rd_en1),                  // input wire rd_en
  .dout(dout1),                    // output wire [15 : 0] dout
  .full(full1),                    // output wire full
  .almost_full(almost_full1),      // output wire almost_full
  .empty(empty1),                  // output wire empty
  .rd_data_count(),  // output wire [9 : 0] rd_data_count
  .wr_data_count(),  // output wire [9 : 0] wr_data_count
  .wr_rst_busy(wr_rst_busy1),      // output wire wr_rst_busy
  .rd_rst_busy(rd_rst_busy1)      // output wire rd_rst_busy
);

image_buffer image_buffer2 (
  .rst(rst_p),                      // input wire rst
  .wr_clk(wr_clk2),                // input wire wr_clk
  .rd_clk(clk_out),                // input wire rd_clk
  .din(data2),                      // input wire [15 : 0] din
  .wr_en(data_valid2),                  // input wire wr_en
  .rd_en(rd_en2),                  // input wire rd_en
  .dout(dout2),                    // output wire [15 : 0] dout
  .full(full2),                    // output wire full
  .almost_full(almost_full2),      // output wire almost_full
  .empty(empty2),                  // output wire empty
  .rd_data_count(),  // output wire [9 : 0] rd_data_count
  .wr_data_count(),  // output wire [9 : 0] wr_data_count
  .wr_rst_busy(wr_rst_busy2),      // output wire wr_rst_busy
  .rd_rst_busy(rd_rst_busy2)      // output wire rd_rst_busy
);
reg image_valid_dly1;
reg image_valid_dly2;

reg rd_en1_dly;
always@(posedge clk_out or posedge rst_p)begin
if(rst_p)
rd_en1_dly <= 1'b0;
else
rd_en1_dly <= rd_en1;
end 

reg rd_en2_dly;
always@(posedge clk_out or posedge rst_p)begin
if(rst_p)
rd_en2_dly <= 1'b0;
else
rd_en2_dly <= rd_en2;
end 


always@(posedge clk_out or negedge rst_p)begin
if(rst_p)begin
image_valid_dly1 <= 1'b0;
image_valid_dly2 <= 1'b0;
end
else begin
image_valid_dly1 <= rd_en1_dly||rd_en2_dly;
image_valid_dly2 <= image_valid_dly1;
end
end

assign image_valid = image_valid_dly1;
always@(posedge clk_out or negedge rst_p)begin
if(rst_p)
image_data <= 16'b0;
else if(rd_en1_dly)
image_data <= dout1;
else if(rd_en2_dly)
image_data <= dout2;
else
image_data <= 16'b0;
end

//always@(posedge clk_out or negedge rst_p)begin
//if(rst_p)
//RD_cnt <= 12'b0;
//else if(next_state == RD_IMG1&&rd_en1_dly)
//RD_cnt <= RD_cnt + 1'b1;
//else if(next_state == RD_IMG2&&rd_en2_dly)
//RD_cnt <= RD_cnt + 1'b1;
//else
//RD_cnt <= 12'b0;
//end


always@(posedge clk_out or negedge rst_p)begin
if(rst_p)
RD_cnt <= 12'b0;
else if((next_state == RD_IMG1)|(next_state == RD_IMG2))begin
if(rd_en2||rd_en1)
RD_cnt <= RD_cnt + 1'b1;
else 
RD_cnt <= RD_cnt;
end
else
RD_cnt <= 12'b0;
end



always@(posedge clk_out or posedge rst_p)begin
if(rst_p)
cur_state <= IDEL;
else
cur_state <= next_state;
end    

always@(posedge clk_out or posedge rst_p)begin
if(rst_p)
image_choose <= 1'b0;
else if(cur_state == RD_IMG1 &&(RD_cnt == image_cnt1))
image_choose <= 1'b1;
else if(cur_state == RD_IMG2 &&(RD_cnt == image_cnt2))
image_choose <= 1'b0;
else
image_choose <= image_choose;
end    

always@(*)
case(cur_state)
IDEL:begin
     if(rst_busy_o == 1'b0)
     next_state = ARB;
     else
     next_state = IDEL;
     end

ARB:begin
    if((image_choose == 1'b0) &&(empty1==1'b0))
    next_state = RD_IMG1;
    else if((image_choose == 1'b1) &&(empty2==1'b0))
    next_state = RD_IMG2;
    else
    next_state = ARB;
    end

RD_IMG1:begin
     if(RD_cnt == image_cnt1)
     next_state = ARB;
     else
     next_state = RD_IMG1;
     end

RD_IMG2:begin     
     if(RD_cnt == image_cnt2)
     next_state = ARB;
     else
     next_state = RD_IMG2;
     end
default:next_state = IDEL;
endcase
   
endmodule
